﻿using AForge.Video;
using AForge.Video.DirectShow;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Media;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WindowsInput;
using ZXing;

namespace QRCodeScanning
{
    public partial class MainForm : Form
    {
        private FilterInfoCollection videoDevices;
        private VideoCaptureDevice videoSource;
        private readonly InputSimulator inputSimulator = new InputSimulator();
        private bool isScanning = false; //控制是否可以扫描

        private Timer scanTimer;
        private bool isScanReady = true; // 控制是否可以进行下一次扫描

        public MainForm()
        {
            InitializeComponent();
            InitializeCameraList();
        }

        private void InitializeCameraList()
        {
            comboBox_outputType.SelectedIndex = 0;
            videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

            foreach (FilterInfo device in videoDevices)
            {
                cboCamera.Items.Add(device.Name);
            }

            if (cboCamera.Items.Count > 0)
            {
                cboCamera.SelectedIndex = 0;
            }
            else
            {
                MessageBox.Show("未检测到摄像头设备，无法使用相关功能！确认后台退出。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                this.Close();
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            // 如果已经在运行，则先停止
            if (videoSource != null && videoSource.IsRunning)
            {
                MessageBox.Show("已开始扫描请不要重复点击开始扫描！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                return;
            }

            videoSource = new VideoCaptureDevice(videoDevices[cboCamera.SelectedIndex].MonikerString);
            videoSource.NewFrame += VideoSource_NewFrame;
            videoSource.Start();

            // 初始化并启动扫描定时器
            if (scanTimer == null)
            {
                scanTimer = new Timer();
                scanTimer.Interval = (int)numTime.Value;
                scanTimer.Tick += (s, args) => { isScanReady = true; };
            }
            else
            {
                // 如果定时器已存在，更新间隔并重新启动
                scanTimer.Interval = (int)numTime.Value;
                scanTimer.Stop();
            }

            scanTimer.Start();

            isScanning = true;
            isScanReady = true; // 立即允许第一次扫描
            lblStatus.Text = "扫描中...";
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            try
            {
                if (videoSource != null && videoSource.IsRunning)
                {
                    videoSource.NewFrame -= VideoSource_NewFrame;
                    videoSource.SignalToStop();

                    int timeout = 2000;
                    int elapsed = 0;
                    int sleepInterval = 100;

                    while (videoSource.IsRunning && elapsed < timeout)
                    {
                        Application.DoEvents();
                        System.Threading.Thread.Sleep(sleepInterval);
                        elapsed += sleepInterval;
                    }

                    if (videoSource.IsRunning)
                    {
                        Debug.WriteLine("视频源停止超时");
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("停止视频源时出错: " + ex.Message);
            }
            finally
            {
                // 停止扫描定时器 更新状态
                if (scanTimer != null && scanTimer.Enabled)
                {
                    scanTimer.Stop();
                }

                isScanning = false;
                lblStatus.Text = "已停止";
                videoSource = null;
            }
        }

        private void VideoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            // 只有当允许扫描且处于扫描状态时才处理
            if (!isScanning || !isScanReady) return;
            var outputType = comboBox_outputType.SelectedIndex;
            try
            {
                using (var bitmap = (Bitmap)eventArgs.Frame.Clone())
                {
                    if (bitmap == null || bitmap.Width == 0 || bitmap.Height == 0) return;

                    var barcodeReader = new BarcodeReader
                    {
                        AutoRotate = true,
                        Options = new ZXing.Common.DecodingOptions
                        {
                            TryHarder = true,
                            PossibleFormats = new List<BarcodeFormat>
                            {
                                BarcodeFormat.QR_CODE,
                                BarcodeFormat.CODE_128,
                                BarcodeFormat.CODE_39,
                                BarcodeFormat.CODE_93,
                                BarcodeFormat.EAN_13,
                                BarcodeFormat.EAN_8,
                                BarcodeFormat.UPC_A,
                                BarcodeFormat.UPC_E,
                                BarcodeFormat.ITF
                            }
                        }
                    };

                    var luminanceSource = new BitmapLuminanceSource(bitmap);
                    var result = barcodeReader.Decode(luminanceSource);

                    // 获取当前聚焦窗口信息并显示
                    this.Invoke((MethodInvoker)delegate
                    {
                        var windowHandle = GetForegroundWindow();
                        if (windowHandle != IntPtr.Zero)
                        {
                            var windowTitle = GetWindowText(windowHandle);
                            lblFocusedWindow.Text = "当前聚焦: " + windowTitle;
                        }
                        else
                        {
                            lblFocusedWindow.Text = "暂无聚焦窗口，无法正常输出";
                        }
                    });

                    if (result != null && !string.IsNullOrEmpty(result.Text))
                    {
                        // 扫描到结果后，设置下次扫描准备状态为false
                        isScanReady = false;

                        // 抓拍摄像头画面 渲染到ui上
                        this.Invoke((MethodInvoker)delegate
                        {
                            //自适应图片大小
                            pictureBox_CodePicture.SizeMode = PictureBoxSizeMode.Zoom;

                            if (pictureBox_CodePicture.Image != null)
                            {
                                pictureBox_CodePicture.Image.Dispose();
                            }

                            pictureBox_CodePicture.Image = (Bitmap)bitmap.Clone();
                        });

                        this.Invoke((MethodInvoker)delegate
                        {
                            try
                            {
                                var windowHandle = GetForegroundWindow();
                                if (windowHandle != IntPtr.Zero)
                                {
                                    if (outputType == 0)
                                    {
                                        // 使用 SendKeys 发送文本
                                        SendKeys.SendWait(result.Text.Replace("+", "{+}")
                                            .Replace("^", "{^}")
                                            .Replace("%", "{%}")
                                            .Replace("~", "{~}")
                                            .Replace("(", "{(}")
                                            .Replace(")", "{)}"));
                                    }
                                    else if (outputType == 1)
                                    {
                                        var windowTitle = GetWindowText(windowHandle);
                                        inputSimulator.Keyboard.TextEntry(result.Text);
                                    }
                                    else if (outputType == 2)
                                    {
                                        // 将结果写入剪贴板
                                        Clipboard.SetText(result.Text);
                                        // 触发 Ctrl+V 快捷键粘贴
                                        inputSimulator.Keyboard.ModifiedKeyStroke(
                                            WindowsInput.Native.VirtualKeyCode.CONTROL,
                                            WindowsInput.Native.VirtualKeyCode.VK_V);
                                    }

                                    if (chkAutoEnter.Checked)
                                    {
                                        SendKeys.SendWait("{ENTER}"); // 发送回车
                                    }

                                    lblLastCode.Text = "上次扫描: " + result.Text + "\r\n时间：" + DateTime.Now.ToString();
                                    SystemSounds.Beep.Play();
                                }
                            }
                            catch (Exception ex)
                            {
                                Debug.WriteLine("输入模拟错误: " + ex.Message);
                            }
                        });

                        if (chkPauseAfterScan.Checked)
                        {
                            isScanning = false;
                            this.Invoke((MethodInvoker)delegate { lblStatus.Text = "已暂停 (扫描到内容)"; });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("解码错误: " + ex.Message);
            }
        }


        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

        private string GetWindowText(IntPtr hWnd)
        {
            const int nChars = 256;
            StringBuilder sb = new StringBuilder(nChars);
            int length = GetWindowText(hWnd, sb, nChars);

            if (length > 0 && length <= nChars)
            {
                int actualLength = Math.Min(length, sb.Length);
                if (actualLength > 0)
                {
                    return sb.ToString(0, actualLength);
                }
            }

            return string.Empty;
        }

        private void btnResume_Click(object sender, EventArgs e)
        {
            isScanning = true;
            isScanReady = true;
            lblStatus.Text = "扫描中...";
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (scanTimer != null)
            {
                scanTimer.Stop();
                scanTimer.Dispose();
                scanTimer = null;
            }

            if (videoSource != null)
            {
                videoSource.NewFrame -= VideoSource_NewFrame;

                if (videoSource.IsRunning)
                {
                    videoSource.SignalToStop();

                    int timeout = 3000;
                    int elapsed = 0;
                    int sleepInterval = 100;

                    while (videoSource.IsRunning && elapsed < timeout)
                    {
                        System.Threading.Thread.Sleep(sleepInterval);
                        elapsed += sleepInterval;
                    }
                }

                videoSource = null;
            }
        }


        private void btnFormTop_Click(object sender, EventArgs e)
        {
            if (this.TopMost)
            {
                this.TopMost = false;
                if (sender is Button button)
                {
                    button.Text = "窗口置顶";
                }
            }
            else
            {
                this.TopMost = true;
                if (sender is Button button)
                {
                    button.Text = "取消置顶";
                }
            }
        }

        private async void btnSelectFile_Click(object sender, EventArgs e)
        {
            Button selectFileButton = sender as Button;
            bool wasEnabled = selectFileButton.Enabled;
            selectFileButton.Enabled = false;
            selectFileButton.Text = "识别中...";
            try
            {
                using (OpenFileDialog openFileDialog = new OpenFileDialog())
                {
                    openFileDialog.Filter = "Image Files|*.jpg;*.jpeg;*.png;*.bmp;*.gif";
                    openFileDialog.Title = "请选择包含二维码/条码的图片";

                    if (openFileDialog.ShowDialog() == DialogResult.OK)
                    {
                        await Task.Run(() =>
                        {
                            try
                            {
                                using (var bitmap = new Bitmap(openFileDialog.FileName))
                                {
                                    var barcodeReader = new BarcodeReader
                                    {
                                        AutoRotate = true,
                                        Options = new ZXing.Common.DecodingOptions
                                        {
                                            TryHarder = true,
                                            PossibleFormats = new List<BarcodeFormat>
                                            {
                                                BarcodeFormat.QR_CODE,
                                                BarcodeFormat.CODE_128,
                                                BarcodeFormat.CODE_39,
                                                BarcodeFormat.CODE_93,
                                                BarcodeFormat.EAN_13,
                                                BarcodeFormat.EAN_8,
                                                BarcodeFormat.UPC_A,
                                                BarcodeFormat.UPC_E,
                                                BarcodeFormat.ITF
                                            }
                                        }
                                    };

                                    var luminanceSource = new BitmapLuminanceSource(bitmap);
                                    var result = barcodeReader.Decode(luminanceSource);
                                    
                                    this.Invoke((MethodInvoker)delegate
                                    {
                                        if (result != null && !string.IsNullOrEmpty(result.Text))
                                        {
                                            pictureBox_CodePicture.SizeMode = PictureBoxSizeMode.Zoom;
                                            if (pictureBox_CodePicture.Image != null)
                                            {
                                                pictureBox_CodePicture.Image.Dispose();
                                            }

                                            pictureBox_CodePicture.Image = (Bitmap)bitmap.Clone();
                                            lblLastCode.Text = "图片扫描结果: " + result.Text + "\r\n时间：" +
                                                               DateTime.Now.ToString();
                                            Clipboard.SetText(result.Text);
                                            MessageBox.Show($"识别到【{result.Text}】已复制到剪切板。", "提示", MessageBoxButtons.OK,
                                                MessageBoxIcon.Information);
                                            SystemSounds.Beep.Play();
                                        }
                                        else
                                        {
                                            MessageBox.Show("未在图片中检测到二维码或条形码。", "提示", MessageBoxButtons.OK,
                                                MessageBoxIcon.Information);
                                        }
                                    });
                                }
                            }
                            catch (Exception ex)
                            {
                                this.Invoke((MethodInvoker)delegate
                                {
                                    MessageBox.Show($"读取图片时发生错误: {ex.Message}", "错误", MessageBoxButtons.OK,
                                        MessageBoxIcon.Error);
                                });
                            }
                        });
                    }
                }
            }
            finally
            {
                selectFileButton.Enabled = wasEnabled;
                selectFileButton.Text = "选择图片";
            }
        }
    }
}